﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using SistemaCenterQuimPost.Plantillas;

using System.Threading; //usado para el proceso batch de actuliazar precios.

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

using SistemaCenterQuimPost.Entidad; //necesario para crear instancias de RegistroUsuario y RegistroListaPrecio en el proceso de archivos.


namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmActualizarPrecios : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //---------ATRIBUTOS--------------------
        private DataSet2 centerQuimDs;  //variables que me permitirán acceder a la base de datos.
        private DataSet2TableAdapters.ProductosTableAdapter productoTa;

        
        //objeto para serializar los RegistroUsuario y RegistroListaPrecio en formato binario
        private BinaryFormatter aplicadorFormato = new BinaryFormatter(); //Clase que permite deserializar objeto, es decir pasarlo a objeto desde binario.
        private FileStream listaPreciosEntrada; //clase que maneja la información sobre el archvi y la forma de abrirlo.
        
        //---------CONSTRUCTORES---------------
        public frmActualizarPrecios()
        {
            InitializeComponent();

            centerQuimDs = new DataSet2();  //variables que me permitirán acceder a la base de datos.
            productoTa = new DataSet2TableAdapters.ProductosTableAdapter();

            

        }


        //----------ESTADOS----------------------

        private void frmActualizarPrecios_Load(object sender, EventArgs e)
        {
            lblError.Visible = false; //al ser un formulario sin estado, este atributo se lee en este lugar.
            
            obtenerArchivosActualizaciones(); //carga el cboArchivo con los archivos.

            cboActualizadores.SelectedItem = 0; //coloca como primer opcion el primer archivo en el comboBox.

        }

        //--------METODOS VARIOS---------------

        private void btnProcesar_Click(object sender, EventArgs e)
        {
            if (cboActualizadores.Items.Count > 0)
            {
                DialogResult result = MessageBox.Show("¿Está seguro que desea actualizar los precios de los productos? ", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    lblEspere.Visible = true;

                    this.Enabled = false; //el formulario se deshabilita mientras actualiza la lista de precios. Es proceso Batch

                    Thread unHilo = new Thread(new ThreadStart(actualizarPrecios));

                    unHilo.Start();

                }

            }else
            {
                
                DialogResult result = MessageBox.Show("No posee actualizadores de precios disponibles.", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
            
            
           
        }

        private void actualizarPrecios()  //actualizamos los precios de los productos. Luego elimina el archivo por seguridad
        {
            
            string nombreArchivo = "C:\\Dropbox\\Datos del Sistema\\Lista de Precios\\" + cboActualizadores.SelectedItem.ToString();

            //guardar el archivo a través del objeto FileStream.
            try
            {
                listaPreciosEntrada = new FileStream(nombreArchivo, FileMode.Open, FileAccess.Read); //crea el objeto FileStream para obtener acceso de lectura al archivo.
                               
                LeerDatos();

                //cuando ya no tiene más datos se lanza la excepcion SerializationException para informar que terminó.

            }

            catch (SerializationException)
            {
                this.Enabled = true;  //el formulario se habilita luego de actualizar la lista de precios. Es proceso Batch


                lblEspere.Visible = false;

                MessageBox.Show("Precios Actualizados con exitos!!", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            catch (FormatException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }

            catch (IOException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("El archivo de lista de precio no se encuentra. \n\n Solicitela a casa central.", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

                this.Enabled = true; //el formulario se habilita luego de actualizar la lista de precios.

                lblEspere.Visible = false;
            }

            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa. /n /n Comuniquese con su desarrollador para solucionar el problema /n /n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                this.Close();
            }

            finally
            {
                cerrarArchivo();

                File.Delete("C:\\Dropbox\\Datos del Sistema\\Lista de Precios\\ListaPrecios.cq"); //eliminamos el archivo.
            }
        }

        private void LeerDatos()
        {
            string fechaActualizacion = "";

            RegistroListaPrecio unRegistroListaPrecio = (RegistroListaPrecio)aplicadorFormato.Deserialize(listaPreciosEntrada);

            fechaActualizacion = unRegistroListaPrecio.FechaActualizacion;
           
            do
            {           //instanciamos unRegistroListaPrecio(Serializado) para ir capturando los objetos del archivo.
                RegistroProductoListaPrecio unRegistroProductoListaPrecio = (RegistroProductoListaPrecio)aplicadorFormato.Deserialize(listaPreciosEntrada);

                        //buscamos el producto y verificamos si hubo cambios en los precios.
                productoTa.FillByNombre(centerQuimDs.Productos, unRegistroProductoListaPrecio.Descripcion);

                if (Convert.ToDateTime(fechaActualizacion) >= Convert.ToDateTime(centerQuimDs.Productos[0].fechaActualización.ToString("d")))
                {
                    centerQuimDs.Productos[0].precioCosto = unRegistroProductoListaPrecio.PrecioCosto;
                    centerQuimDs.Productos[0].precioVenta = unRegistroProductoListaPrecio.PrecioVenta;
                    centerQuimDs.Productos[0].fechaActualización = Convert.ToDateTime(obtenerFechaActual());

                    productoTa.Update(centerQuimDs.Productos);  //actualiza los precios y la fecha de actualización.

                }

            } while (listaPreciosEntrada != null);
        }


        private void cerrarArchivo()
        {
            try
            {
                if (listaPreciosEntrada != null)  //determina si existe el archivo
                {
                    listaPreciosEntrada.Close();  //cierra el archivo

                    File.Delete(listaPreciosEntrada.Name); //eliminamos el archivo.

                    obtenerArchivosActualizaciones(); //se vuelve a actualizar el combo.
                }
            }
            catch (IOException)  //notifica al usuario del error al cerrar el archivo
            {
                MessageBox.Show("No se puede cerrar el archivo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private string obtenerFechaActual()  //Dato necesario para el alta de venta
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private void obtenerArchivosActualizaciones()  //carga en el cboActualizadores los archivos de actualizaciones de precios disponibles.
        {
            this.cboActualizadores.Items.Clear(); //borra todo lo que tenía antes. 

            string directorioPrecios = "C:\\Dropbox\\Datos del Sistema\\Lista de Precios"; //seteamos el directorio desde donde leeremos los archivos

            foreach (string archivo in Directory.GetFiles(directorioPrecios))  //por cada archvio en este directorio
            {
                FileInfo archivoInfo = new FileInfo(archivo);  //obtenemos información de ese directorio

                cboActualizadores.Items.Add(archivoInfo.Name); //mostramos solo su nombre corto.

            }

        }

    }
}
